
// 主进程：增加文件选择与文件信息获取能力，适配 Electron × 鸿蒙
// 说明：通过 IPC 暴露文件选择对话框与文件信息查询，渲染层在 contextIsolation 下安全使用。
const { app, BrowserWindow, Tray, nativeImage, Menu, ipcMain, dialog } = require('electron');
const path = require('path');
const fs = require('fs');

let mainWindow, tray;

function createWindow() {
    // 创建系统托盘（注意：确保同级目录有electron_white.png图片）
    const trayIcon = nativeImage.createFromPath(path.join(__dirname, 'electron_white.png'));
    tray = new Tray(trayIcon);

    // 创建托盘右键菜单
    const trayMenu = Menu.buildFromTemplate([
        { 
            label: '显示窗口', 
            click: () => {
                mainWindow.show(); // 显示窗口
                mainWindow.focus(); // 聚焦窗口
            } 
        },
        { type: 'separator' }, // 分隔线
        { 
            label: '退出应用', 
            click: () => {
                // 退出前清理托盘和窗口
                tray.destroy();
                mainWindow.destroy();
                app.quit();
            } 
        }
    ]);
    tray.setContextMenu(trayMenu); // 绑定菜单到托盘


    // 创建主窗口
    mainWindow = new BrowserWindow({
        width: 800,
        height: 600,
        title: 'electron桌面版', // 窗口标题
        // 可选：添加窗口图标（替换为你的图标路径）
        // icon: path.join(__dirname, 'window_icon.png'),
        webPreferences: {
            nodeIntegration: false, // 禁用node集成（安全最佳实践）
            contextIsolation: true, // 启用上下文隔离（安全最佳实践）
            // 指定预加载脚本：用于在渲染层安全地注入平台信息到页面
            preload: path.join(__dirname, 'preload.js')
        }
    });

    // 适配macOS窗口按钮
    mainWindow.setWindowButtonVisibility(true);

    // 加载本地页面显示平台信息
    mainWindow.loadFile(path.join(__dirname, 'index.html'));


    // 窗口关闭时最小化到托盘（而非直接退出）
    mainWindow.on('close', (e) => {
        // 仅在用户主动退出时才真正关闭（避免托盘菜单"退出"被拦截）
        if (app.quitting) {
            mainWindow = null;
        } else {
            e.preventDefault(); // 阻止默认关闭行为
            mainWindow.hide(); // 隐藏窗口到托盘
        }
    });


    // 点击托盘图标切换窗口显示/隐藏
    tray.on('click', () => {
        if (mainWindow.isVisible()) {
            mainWindow.hide();
        } else {
            mainWindow.show();
            mainWindow.focus();
        }
    });


    // 可选：窗口隐藏时在托盘显示提示
    mainWindow.on('hide', () => {
        tray.displayBalloon({
            title: '应用已最小化',
            content: '点击托盘图标恢复窗口'
        });
    });
}

// 应用就绪后创建窗口，并注册文件选择 IPC 接口
app.whenReady()
  .then(createWindow)
  .then(() => {
    /**
     * 渲染层调用：选择文件对话框
     * @param {Electron.IpcMainInvokeEvent} _event - IPC 调用事件（未使用）
     * @param {Object} options - 对话框自定义参数（可选），与 Electron 的 showOpenDialog 选项一致
     * @returns {Promise<Electron.OpenDialogReturnValue>} 包含是否取消与选中文件路径的返回值
     * 说明：
     * - 默认允许选择多个文件（multiSelections），可通过 options.properties 覆盖
     * - 在鸿蒙容器中，底层 Electron 的对话框能力将由容器适配具体实现
     */
    ipcMain.handle('select-files', async (_event, options = {}) => {
      const defaultOptions = {
        title: '选择文件',
        properties: ['openFile', 'multiSelections'],
        // 可选：根据业务添加过滤器，例如只选择图片或文本
        // filters: [{ name: 'All Files', extensions: ['*'] }]
      };
      const merged = { ...defaultOptions, ...options };
      const result = await dialog.showOpenDialog(mainWindow ?? undefined, merged);
      return result; // { canceled: boolean, filePaths: string[] }
    });

    /**
     * 渲染层调用：获取文件详细信息（含元数据与文本预览）
     * @param {Electron.IpcMainInvokeEvent} _event - IPC 调用事件
     * @param {string[]} filePaths - 选中的文件绝对路径列表
     * @param {Object} options - 可选参数：{ previewBytes?: number }
     * @returns {Promise<Array>} 文件信息数组
     * 说明：
     * - 默认预览前 4096 字节，只在文本类扩展名时尝试预览
     * - 文本类型判断采用扩展名白名单（避免误读二进制）
     */
    ipcMain.handle('get-file-info', async (_event, filePaths = [], options = {}) => {
      const previewBytes = Math.max(512, Math.min(128 * 1024, options.previewBytes ?? 4096));
      const maxTextFullRead = Math.max(16 * 1024, Math.min(512 * 1024, options.maxTextFullRead ?? 256 * 1024));
      const textExts = new Set(['txt','md','markdown','json','js','ts','jsx','tsx','html','htm','css','scss','less','xml','yml','yaml','csv','log','ini','conf']);
      const imageExts = new Set(['png','jpg','jpeg','gif','webp','bmp','svg']);

      const toInfo = async (p) => {
        try {
          const stat = await fs.promises.stat(p);
          const ext = (path.extname(p).toLowerCase().replace(/^\./, ''));
          const isText = textExts.has(ext);
          const isImage = imageExts.has(ext);
          let preview = undefined;
          let previewTruncated = false;
          let imageUrl = undefined;
          let mime = undefined;

          if (isText && stat.isFile()) {
            // 文本：小文件直接完整读取；大文件读取前 previewBytes 字节
            const fh = await fs.promises.open(p, 'r');
            try {
              if (stat.size <= maxTextFullRead) {
                const buf = Buffer.alloc(stat.size);
                const { bytesRead } = await fh.read(buf, 0, stat.size, 0);
                preview = buf.subarray(0, bytesRead).toString('utf8');
                previewTruncated = false;
              } else {
                const buf = Buffer.alloc(previewBytes);
                const { bytesRead } = await fh.read(buf, 0, previewBytes, 0);
                preview = buf.subarray(0, bytesRead).toString('utf8');
                previewTruncated = true;
              }
            } finally {
              await fh.close();
            }
          }

          if (isImage && stat.isFile()) {
            // 图片：不读取内容，使用 file:// URL 供渲染层直接展示
            imageUrl = `file://${p}`;
            // 基于扩展名推断简单 MIME（非严格）
            const extToMime = {
              png: 'image/png', jpg: 'image/jpeg', jpeg: 'image/jpeg', gif: 'image/gif', webp: 'image/webp', bmp: 'image/bmp', svg: 'image/svg+xml'
            };
            mime = extToMime[ext] ?? undefined;
          }

          return {
            path: p,
            name: path.basename(p),
            size: stat.size,
            isDirectory: stat.isDirectory(),
            mtimeMs: stat.mtimeMs,
            ctimeMs: stat.ctimeMs,
            mtime: stat.mtime.toISOString(),
            ctime: stat.ctime.toISOString(),
            ext,
            isText,
            isImage,
            preview,
            previewTruncated,
            imageUrl,
            mime,
          };
        } catch (err) {
          return {
            path: p,
            error: String(err?.message ?? err),
          };
        }
      };

      const results = await Promise.all((filePaths || []).map(toInfo));
      return results;
    });
  });

// 处理不同平台的窗口关闭逻辑
app.on('window-all-closed', () => {
    // macOS：应用通常在所有窗口关闭后仍保持运行
    if (process.platform !== 'darwin') {
        app.quit();
    }
});

// macOS：点击dock图标时重新创建窗口
app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
        createWindow();
    } else {
        mainWindow.show();
    }
});

// 标记应用是否正在退出（用于区分关闭窗口和退出应用）
app.on('before-quit', () => {
    app.quitting = true;
});